Skip to main content

std/os/windows/io/
handle.rs

1//! Owned and borrowed OS handles.
2
3#![stable(feature = "io_safety", since = "1.63.0")]
4
5use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
6use crate::alloc::Allocator;
7use crate::marker::PhantomData;
8use crate::mem::ManuallyDrop;
9use crate::sys::{AsInner, FromInner, IntoInner, cvt};
10use crate::{fmt, fs, io, ptr, sys};
11
12/// A borrowed handle.
13///
14/// This has a lifetime parameter to tie it to the lifetime of something that
15/// owns the handle.
16///
17/// This uses `repr(transparent)` and has the representation of a host handle,
18/// so it can be used in FFI in places where a handle is passed as an argument,
19/// it is not captured or consumed.
20///
21/// Note that it *may* have the value `-1`, which in `BorrowedHandle` always
22/// represents a valid handle value, such as [the current process handle], and
23/// not `INVALID_HANDLE_VALUE`, despite the two having the same value. See
24/// [here] for the full story.
25///
26/// And, it *may* have the value `NULL` (0), which can occur when consoles are
27/// detached from processes, or when `windows_subsystem` is used.
28///
29/// This type's `.to_owned()` implementation returns another `BorrowedHandle`
30/// rather than an `OwnedHandle`. It just makes a trivial copy of the raw
31/// handle, which is then borrowed under the same lifetime.
32///
33/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
34/// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
35#[derive(Copy, Clone)]
36#[repr(transparent)]
37#[stable(feature = "io_safety", since = "1.63.0")]
38pub struct BorrowedHandle<'handle> {
39    handle: RawHandle,
40    _phantom: PhantomData<&'handle OwnedHandle>,
41}
42
43/// An owned handle.
44///
45/// This closes the handle on drop.
46///
47/// Note that it *may* have the value `-1`, which in `OwnedHandle` always
48/// represents a valid handle value, such as [the current process handle], and
49/// not `INVALID_HANDLE_VALUE`, despite the two having the same value. See
50/// [here] for the full story.
51///
52/// And, it *may* have the value `NULL` (0), which can occur when consoles are
53/// detached from processes, or when `windows_subsystem` is used.
54///
55/// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such,
56/// it must not be used with handles to open registry keys which need to be
57/// closed with [`RegCloseKey`] instead.
58///
59/// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
60/// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
61///
62/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
63/// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
64#[repr(transparent)]
65#[stable(feature = "io_safety", since = "1.63.0")]
66pub struct OwnedHandle {
67    handle: RawHandle,
68}
69
70/// FFI type for handles in return values or out parameters, where `NULL` is used
71/// as a sentry value to indicate errors, such as in the return value of `CreateThread`. This uses
72/// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
73/// FFI declarations.
74///
75/// The only thing you can usefully do with a `HandleOrNull` is to convert it into an
76/// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
77/// `NULL`. This ensures that such FFI calls cannot start using the handle without
78/// checking for `NULL` first.
79///
80/// This type may hold any handle value that [`OwnedHandle`] may hold. As with `OwnedHandle`, when
81/// it holds `-1`, that value is interpreted as a valid handle value, such as
82/// [the current process handle], and not `INVALID_HANDLE_VALUE`.
83///
84/// If this holds a non-null handle, it will close the handle on drop.
85///
86/// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
87#[repr(transparent)]
88#[stable(feature = "io_safety", since = "1.63.0")]
89#[derive(Debug)]
90pub struct HandleOrNull(RawHandle);
91
92/// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used
93/// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses
94/// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
95/// FFI declarations.
96///
97/// The only thing you can usefully do with a `HandleOrInvalid` is to convert it into an
98/// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
99/// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without
100/// checking for `INVALID_HANDLE_VALUE` first.
101///
102/// This type may hold any handle value that [`OwnedHandle`] may hold, except that when it holds
103/// `-1`, that value is interpreted to mean `INVALID_HANDLE_VALUE`.
104///
105/// If holds a handle other than `INVALID_HANDLE_VALUE`, it will close the handle on drop.
106#[repr(transparent)]
107#[stable(feature = "io_safety", since = "1.63.0")]
108#[derive(Debug)]
109pub struct HandleOrInvalid(RawHandle);
110
111// The Windows [`HANDLE`] type may be transferred across and shared between
112// thread boundaries (despite containing a `*mut void`, which in general isn't
113// `Send` or `Sync`).
114//
115// [`HANDLE`]: std::os::windows::raw::HANDLE
116#[stable(feature = "io_safety", since = "1.63.0")]
117unsafe impl Send for OwnedHandle {}
118#[stable(feature = "io_safety", since = "1.63.0")]
119unsafe impl Send for HandleOrNull {}
120#[stable(feature = "io_safety", since = "1.63.0")]
121unsafe impl Send for HandleOrInvalid {}
122#[stable(feature = "io_safety", since = "1.63.0")]
123unsafe impl Send for BorrowedHandle<'_> {}
124#[stable(feature = "io_safety", since = "1.63.0")]
125unsafe impl Sync for OwnedHandle {}
126#[stable(feature = "io_safety", since = "1.63.0")]
127unsafe impl Sync for HandleOrNull {}
128#[stable(feature = "io_safety", since = "1.63.0")]
129unsafe impl Sync for HandleOrInvalid {}
130#[stable(feature = "io_safety", since = "1.63.0")]
131unsafe impl Sync for BorrowedHandle<'_> {}
132
133impl BorrowedHandle<'_> {
134    /// Returns a `BorrowedHandle` holding the given raw handle.
135    ///
136    /// # Safety
137    ///
138    /// The resource pointed to by `handle` must be a valid open handle, it
139    /// must remain open for the duration of the returned `BorrowedHandle`.
140    ///
141    /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
142    /// sometimes a valid handle value. See [here] for the full story.
143    ///
144    /// And, it *may* have the value `NULL` (0), which can occur when consoles are
145    /// detached from processes, or when `windows_subsystem` is used.
146    ///
147    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
148    #[inline]
149    #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
150    #[stable(feature = "io_safety", since = "1.63.0")]
151    pub const unsafe fn borrow_raw(handle: RawHandle) -> Self {
152        Self { handle, _phantom: PhantomData }
153    }
154}
155
156#[stable(feature = "io_safety", since = "1.63.0")]
157impl TryFrom<HandleOrNull> for OwnedHandle {
158    type Error = NullHandleError;
159
160    #[inline]
161    fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> {
162        let handle_or_null = ManuallyDrop::new(handle_or_null);
163        if handle_or_null.is_valid() {
164            // SAFETY: The handle is not null.
165            Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_null.0) })
166        } else {
167            Err(NullHandleError(()))
168        }
169    }
170}
171
172#[stable(feature = "io_safety", since = "1.63.0")]
173impl Drop for HandleOrNull {
174    #[inline]
175    fn drop(&mut self) {
176        if self.is_valid() {
177            unsafe {
178                let _ = sys::c::CloseHandle(self.0);
179            }
180        }
181    }
182}
183
184impl OwnedHandle {
185    /// Creates a new `OwnedHandle` instance that shares the same underlying
186    /// object as the existing `OwnedHandle` instance.
187    #[stable(feature = "io_safety", since = "1.63.0")]
188    pub fn try_clone(&self) -> io::Result<Self> {
189        self.as_handle().try_clone_to_owned()
190    }
191}
192
193impl BorrowedHandle<'_> {
194    /// Creates a new `OwnedHandle` instance that shares the same underlying
195    /// object as the existing `BorrowedHandle` instance.
196    #[stable(feature = "io_safety", since = "1.63.0")]
197    pub fn try_clone_to_owned(&self) -> io::Result<OwnedHandle> {
198        self.duplicate(0, false, sys::c::DUPLICATE_SAME_ACCESS)
199    }
200
201    pub(crate) fn duplicate(
202        &self,
203        access: u32,
204        inherit: bool,
205        options: u32,
206    ) -> io::Result<OwnedHandle> {
207        let handle = self.as_raw_handle();
208
209        // `Stdin`, `Stdout`, and `Stderr` can all hold null handles, such as
210        // in a process with a detached console. `DuplicateHandle` would fail
211        // if we passed it a null handle, but we can treat null as a valid
212        // handle which doesn't do any I/O, and allow it to be duplicated.
213        if handle.is_null() {
214            return unsafe { Ok(OwnedHandle::from_raw_handle(handle)) };
215        }
216
217        let mut ret = ptr::null_mut();
218        cvt(unsafe {
219            let cur_proc = sys::c::GetCurrentProcess();
220            sys::c::DuplicateHandle(
221                cur_proc,
222                handle,
223                cur_proc,
224                &mut ret,
225                access,
226                inherit as sys::c::BOOL,
227                options,
228            )
229        })?;
230        unsafe { Ok(OwnedHandle::from_raw_handle(ret)) }
231    }
232}
233
234#[stable(feature = "io_safety", since = "1.63.0")]
235impl TryFrom<HandleOrInvalid> for OwnedHandle {
236    type Error = InvalidHandleError;
237
238    #[inline]
239    fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> {
240        let handle_or_invalid = ManuallyDrop::new(handle_or_invalid);
241        if handle_or_invalid.is_valid() {
242            // SAFETY: The handle is not invalid.
243            Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_invalid.0) })
244        } else {
245            Err(InvalidHandleError(()))
246        }
247    }
248}
249
250#[stable(feature = "io_safety", since = "1.63.0")]
251impl Drop for HandleOrInvalid {
252    #[inline]
253    fn drop(&mut self) {
254        if self.is_valid() {
255            unsafe {
256                let _ = sys::c::CloseHandle(self.0);
257            }
258        }
259    }
260}
261
262/// This is the error type used by [`HandleOrNull`] when attempting to convert
263/// into a handle, to indicate that the value is null.
264// The empty field prevents constructing this, and allows extending it in the future.
265#[stable(feature = "io_safety", since = "1.63.0")]
266#[derive(Debug, Clone, PartialEq, Eq)]
267pub struct NullHandleError(());
268
269#[stable(feature = "io_safety", since = "1.63.0")]
270impl fmt::Display for NullHandleError {
271    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
272        "A HandleOrNull could not be converted to a handle because it was null".fmt(fmt)
273    }
274}
275
276#[stable(feature = "io_safety", since = "1.63.0")]
277impl crate::error::Error for NullHandleError {}
278
279/// This is the error type used by [`HandleOrInvalid`] when attempting to
280/// convert into a handle, to indicate that the value is
281/// `INVALID_HANDLE_VALUE`.
282// The empty field prevents constructing this, and allows extending it in the future.
283#[stable(feature = "io_safety", since = "1.63.0")]
284#[derive(Debug, Clone, PartialEq, Eq)]
285pub struct InvalidHandleError(());
286
287#[stable(feature = "io_safety", since = "1.63.0")]
288impl fmt::Display for InvalidHandleError {
289    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
290        "A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE"
291            .fmt(fmt)
292    }
293}
294
295#[stable(feature = "io_safety", since = "1.63.0")]
296impl crate::error::Error for InvalidHandleError {}
297
298#[stable(feature = "io_safety", since = "1.63.0")]
299impl AsRawHandle for BorrowedHandle<'_> {
300    #[inline]
301    fn as_raw_handle(&self) -> RawHandle {
302        self.handle
303    }
304}
305
306#[stable(feature = "io_safety", since = "1.63.0")]
307impl AsRawHandle for OwnedHandle {
308    #[inline]
309    fn as_raw_handle(&self) -> RawHandle {
310        self.handle
311    }
312}
313
314#[stable(feature = "io_safety", since = "1.63.0")]
315impl IntoRawHandle for OwnedHandle {
316    #[inline]
317    fn into_raw_handle(self) -> RawHandle {
318        ManuallyDrop::new(self).handle
319    }
320}
321
322#[stable(feature = "io_safety", since = "1.63.0")]
323impl FromRawHandle for OwnedHandle {
324    #[inline]
325    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
326        Self { handle }
327    }
328}
329
330impl HandleOrNull {
331    /// Constructs a new instance of `Self` from the given `RawHandle` returned
332    /// from a Windows API that uses null to indicate failure, such as
333    /// `CreateThread`.
334    ///
335    /// Use `HandleOrInvalid` instead of `HandleOrNull` for APIs that
336    /// use `INVALID_HANDLE_VALUE` to indicate failure.
337    ///
338    /// # Safety
339    ///
340    /// The passed `handle` value must either satisfy the safety requirements
341    /// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all
342    /// Windows APIs use null for errors; see [here] for the full story.
343    ///
344    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
345    #[stable(feature = "io_safety", since = "1.63.0")]
346    #[inline]
347    pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
348        Self(handle)
349    }
350
351    fn is_valid(&self) -> bool {
352        !self.0.is_null()
353    }
354}
355
356impl HandleOrInvalid {
357    /// Constructs a new instance of `Self` from the given `RawHandle` returned
358    /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
359    /// failure, such as `CreateFileW`.
360    ///
361    /// Use `HandleOrNull` instead of `HandleOrInvalid` for APIs that
362    /// use null to indicate failure.
363    ///
364    /// # Safety
365    ///
366    /// The passed `handle` value must either satisfy the safety requirements
367    /// of [`FromRawHandle::from_raw_handle`], or be
368    /// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use
369    /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story.
370    ///
371    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
372    #[stable(feature = "io_safety", since = "1.63.0")]
373    #[inline]
374    pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
375        Self(handle)
376    }
377
378    fn is_valid(&self) -> bool {
379        self.0 != sys::c::INVALID_HANDLE_VALUE
380    }
381}
382
383#[stable(feature = "io_safety", since = "1.63.0")]
384impl Drop for OwnedHandle {
385    #[inline]
386    fn drop(&mut self) {
387        unsafe {
388            let _ = sys::c::CloseHandle(self.handle);
389        }
390    }
391}
392
393#[stable(feature = "io_safety", since = "1.63.0")]
394impl fmt::Debug for BorrowedHandle<'_> {
395    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396        f.debug_struct("BorrowedHandle").field("handle", &self.handle).finish()
397    }
398}
399
400#[stable(feature = "io_safety", since = "1.63.0")]
401impl fmt::Debug for OwnedHandle {
402    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403        f.debug_struct("OwnedHandle").field("handle", &self.handle).finish()
404    }
405}
406
407macro_rules! impl_is_terminal {
408    ($($t:ty),*$(,)?) => {$(
409        #[stable(feature = "is_terminal", since = "1.70.0")]
410        impl io::IsTerminal for $t {
411            #[inline]
412            fn is_terminal(&self) -> bool {
413                crate::sys::io::is_terminal(self)
414            }
415        }
416    )*}
417}
418
419impl_is_terminal!(BorrowedHandle<'_>, OwnedHandle);
420
421/// A trait to borrow the handle from an underlying object.
422#[stable(feature = "io_safety", since = "1.63.0")]
423pub trait AsHandle {
424    /// Borrows the handle.
425    ///
426    /// # Example
427    ///
428    #[cfg_attr(windows, doc = "```no_run")]
429    #[cfg_attr(not(windows), doc = "```ignore (needs windows)")]
430    /// use std::fs::File;
431    /// # use std::io;
432    /// use std::os::windows::io::{AsHandle, BorrowedHandle};
433    ///
434    /// let mut f = File::open("foo.txt")?;
435    /// let borrowed_handle: BorrowedHandle<'_> = f.as_handle();
436    /// # Ok::<(), io::Error>(())
437    /// ```
438    #[stable(feature = "io_safety", since = "1.63.0")]
439    fn as_handle(&self) -> BorrowedHandle<'_>;
440}
441
442#[stable(feature = "io_safety", since = "1.63.0")]
443impl<T: AsHandle + ?Sized> AsHandle for &T {
444    #[inline]
445    fn as_handle(&self) -> BorrowedHandle<'_> {
446        T::as_handle(self)
447    }
448}
449
450#[stable(feature = "io_safety", since = "1.63.0")]
451impl<T: AsHandle + ?Sized> AsHandle for &mut T {
452    #[inline]
453    fn as_handle(&self) -> BorrowedHandle<'_> {
454        T::as_handle(self)
455    }
456}
457
458#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
459/// This impl allows implementing traits that require `AsHandle` on Arc.
460/// ```
461/// # #[cfg(windows)] mod group_cfg {
462/// # use std::os::windows::io::AsHandle;
463/// use std::fs::File;
464/// use std::sync::Arc;
465///
466/// trait MyTrait: AsHandle {}
467/// impl MyTrait for Arc<File> {}
468/// impl MyTrait for Box<File> {}
469/// # }
470/// ```
471impl<T: AsHandle + ?Sized> AsHandle for crate::sync::Arc<T> {
472    #[inline]
473    fn as_handle(&self) -> BorrowedHandle<'_> {
474        (**self).as_handle()
475    }
476}
477
478#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
479impl<T: AsHandle + ?Sized> AsHandle for crate::rc::Rc<T> {
480    #[inline]
481    fn as_handle(&self) -> BorrowedHandle<'_> {
482        (**self).as_handle()
483    }
484}
485
486#[unstable(feature = "unique_rc_arc", issue = "112566")]
487impl<T: AsHandle + ?Sized> AsHandle for crate::rc::UniqueRc<T> {
488    #[inline]
489    fn as_handle(&self) -> BorrowedHandle<'_> {
490        (**self).as_handle()
491    }
492}
493
494#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
495impl<T: AsHandle + ?Sized, A: Allocator> AsHandle for Box<T, A> {
496    #[inline]
497    fn as_handle(&self) -> BorrowedHandle<'_> {
498        (**self).as_handle()
499    }
500}
501
502#[stable(feature = "io_safety", since = "1.63.0")]
503impl AsHandle for BorrowedHandle<'_> {
504    #[inline]
505    fn as_handle(&self) -> BorrowedHandle<'_> {
506        *self
507    }
508}
509
510#[stable(feature = "io_safety", since = "1.63.0")]
511impl AsHandle for OwnedHandle {
512    #[inline]
513    fn as_handle(&self) -> BorrowedHandle<'_> {
514        // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
515        // invariants, and the `BorrowedHandle` is bounded by the lifetime
516        // of `&self`.
517        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
518    }
519}
520
521#[stable(feature = "io_safety", since = "1.63.0")]
522impl AsHandle for fs::File {
523    #[inline]
524    fn as_handle(&self) -> BorrowedHandle<'_> {
525        self.as_inner().as_handle()
526    }
527}
528
529#[stable(feature = "io_safety", since = "1.63.0")]
530impl From<fs::File> for OwnedHandle {
531    /// Takes ownership of a [`File`](fs::File)'s underlying file handle.
532    #[inline]
533    fn from(file: fs::File) -> OwnedHandle {
534        file.into_inner().into_inner().into_inner()
535    }
536}
537
538#[stable(feature = "io_safety", since = "1.63.0")]
539impl From<OwnedHandle> for fs::File {
540    /// Returns a [`File`](fs::File) that takes ownership of the given handle.
541    #[inline]
542    fn from(owned: OwnedHandle) -> Self {
543        Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned)))
544    }
545}
546
547#[stable(feature = "io_safety", since = "1.63.0")]
548impl AsHandle for io::Stdin {
549    #[inline]
550    fn as_handle(&self) -> BorrowedHandle<'_> {
551        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
552    }
553}
554
555#[stable(feature = "io_safety", since = "1.63.0")]
556impl<'a> AsHandle for io::StdinLock<'a> {
557    #[inline]
558    fn as_handle(&self) -> BorrowedHandle<'_> {
559        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
560    }
561}
562
563#[stable(feature = "io_safety", since = "1.63.0")]
564impl AsHandle for io::Stdout {
565    #[inline]
566    fn as_handle(&self) -> BorrowedHandle<'_> {
567        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
568    }
569}
570
571#[stable(feature = "io_safety", since = "1.63.0")]
572impl<'a> AsHandle for io::StdoutLock<'a> {
573    #[inline]
574    fn as_handle(&self) -> BorrowedHandle<'_> {
575        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
576    }
577}
578
579#[stable(feature = "io_safety", since = "1.63.0")]
580impl AsHandle for io::Stderr {
581    #[inline]
582    fn as_handle(&self) -> BorrowedHandle<'_> {
583        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
584    }
585}
586
587#[stable(feature = "io_safety", since = "1.63.0")]
588impl<'a> AsHandle for io::StderrLock<'a> {
589    #[inline]
590    fn as_handle(&self) -> BorrowedHandle<'_> {
591        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
592    }
593}
594
595#[stable(feature = "io_safety", since = "1.63.0")]
596impl AsHandle for crate::process::ChildStdin {
597    #[inline]
598    fn as_handle(&self) -> BorrowedHandle<'_> {
599        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
600    }
601}
602
603#[stable(feature = "io_safety", since = "1.63.0")]
604impl From<crate::process::ChildStdin> for OwnedHandle {
605    /// Takes ownership of a [`ChildStdin`](crate::process::ChildStdin)'s file handle.
606    #[inline]
607    fn from(child_stdin: crate::process::ChildStdin) -> OwnedHandle {
608        unsafe { OwnedHandle::from_raw_handle(child_stdin.into_raw_handle()) }
609    }
610}
611
612#[stable(feature = "io_safety", since = "1.63.0")]
613impl AsHandle for crate::process::ChildStdout {
614    #[inline]
615    fn as_handle(&self) -> BorrowedHandle<'_> {
616        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
617    }
618}
619
620#[stable(feature = "io_safety", since = "1.63.0")]
621impl From<crate::process::ChildStdout> for OwnedHandle {
622    /// Takes ownership of a [`ChildStdout`](crate::process::ChildStdout)'s file handle.
623    #[inline]
624    fn from(child_stdout: crate::process::ChildStdout) -> OwnedHandle {
625        unsafe { OwnedHandle::from_raw_handle(child_stdout.into_raw_handle()) }
626    }
627}
628
629#[stable(feature = "io_safety", since = "1.63.0")]
630impl AsHandle for crate::process::ChildStderr {
631    #[inline]
632    fn as_handle(&self) -> BorrowedHandle<'_> {
633        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
634    }
635}
636
637#[stable(feature = "io_safety", since = "1.63.0")]
638impl From<crate::process::ChildStderr> for OwnedHandle {
639    /// Takes ownership of a [`ChildStderr`](crate::process::ChildStderr)'s file handle.
640    #[inline]
641    fn from(child_stderr: crate::process::ChildStderr) -> OwnedHandle {
642        unsafe { OwnedHandle::from_raw_handle(child_stderr.into_raw_handle()) }
643    }
644}
645
646#[stable(feature = "io_safety", since = "1.63.0")]
647impl<T> AsHandle for crate::thread::JoinHandle<T> {
648    #[inline]
649    fn as_handle(&self) -> BorrowedHandle<'_> {
650        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
651    }
652}
653
654#[stable(feature = "io_safety", since = "1.63.0")]
655impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
656    #[inline]
657    fn from(join_handle: crate::thread::JoinHandle<T>) -> OwnedHandle {
658        join_handle.into_inner().into_handle().into_inner()
659    }
660}
661
662#[stable(feature = "anonymous_pipe", since = "1.87.0")]
663impl AsHandle for io::PipeReader {
664    fn as_handle(&self) -> BorrowedHandle<'_> {
665        self.0.as_handle()
666    }
667}
668
669#[stable(feature = "anonymous_pipe", since = "1.87.0")]
670impl From<io::PipeReader> for OwnedHandle {
671    fn from(pipe: io::PipeReader) -> Self {
672        pipe.into_inner().into_inner()
673    }
674}
675
676#[stable(feature = "anonymous_pipe", since = "1.87.0")]
677impl AsHandle for io::PipeWriter {
678    fn as_handle(&self) -> BorrowedHandle<'_> {
679        self.0.as_handle()
680    }
681}
682
683#[stable(feature = "anonymous_pipe", since = "1.87.0")]
684impl From<io::PipeWriter> for OwnedHandle {
685    fn from(pipe: io::PipeWriter) -> Self {
686        pipe.into_inner().into_inner()
687    }
688}
689
690#[stable(feature = "anonymous_pipe", since = "1.87.0")]
691impl From<OwnedHandle> for io::PipeReader {
692    fn from(owned_handle: OwnedHandle) -> Self {
693        Self::from_inner(FromInner::from_inner(owned_handle))
694    }
695}
696
697#[stable(feature = "anonymous_pipe", since = "1.87.0")]
698impl From<OwnedHandle> for io::PipeWriter {
699    fn from(owned_handle: OwnedHandle) -> Self {
700        Self::from_inner(FromInner::from_inner(owned_handle))
701    }
702}